#include "stdafx.h"
#include "gp.h"
#include "gp_Ax2.h"
#include "gp_Ax1.h"
#include "gp_Pnt.h"
#include "gp_Trsf.h"
#include "gp_Vec.h"
#include "gp_Hypr.h"

void gp_Hypr::Mirror (const gp_Pnt& P)
{ pos.Mirror(P); }

gp_Hypr gp_Hypr::Mirrored (const gp_Pnt& P) const
{
	gp_Hypr H = *this;
	H.pos.Mirror(P);
	return H; 
}

void gp_Hypr::Mirror (const gp_Ax1& A1)
{ pos.Mirror(A1); }

gp_Hypr gp_Hypr::Mirrored (const gp_Ax1& A1) const
{
	gp_Hypr H = *this;
	H.pos.Mirror(A1);
	return H; 
}

void gp_Hypr::Mirror (const gp_Ax2& A2)
{ pos.Mirror(A2); }

gp_Hypr gp_Hypr::Mirrored (const gp_Ax2& A2) const
{
	gp_Hypr H = *this;
	H.pos.Mirror(A2);
	return H; 
}
 gp_Hypr::gp_Hypr () :
majorRadius(DBL_MAX),
minorRadius(RealFirst())
{ }

 gp_Hypr::gp_Hypr (const gp_Ax2& A2,
			 const double MajorRadius,
			 const double MinorRadius):
			 pos(A2),
			 majorRadius(MajorRadius),
			 minorRadius(MinorRadius)
{ 
  Standard_ConstructionError_Raise_if
    (MinorRadius < 0.0 || MajorRadius < 0.0,"");
}

 void gp_Hypr::SetAxis (const gp_Ax1& A1)
{ pos.SetAxis (A1); }

 void gp_Hypr::SetLocation (const gp_Pnt& P)
{ pos = gp_Ax2 (P, pos.Direction(), pos.XDirection()); }

 void gp_Hypr::SetMajorRadius (const double R)
{
  Standard_ConstructionError_Raise_if(R < 0.0,"");
  majorRadius = R;
}

 void gp_Hypr::SetMinorRadius (const double R)
{
  Standard_ConstructionError_Raise_if(R < 0.0,"");
  minorRadius = R;
}

 void gp_Hypr::SetPosition (const gp_Ax2& A2)
{ pos = A2; }

 gp_Ax1 gp_Hypr::Asymptote1 () const
{
  Standard_ConstructionError_Raise_if
    (majorRadius <= gp::Resolution(), "");
  gp_Vec V1 = gp_Vec (pos.YDirection());
  V1.Multiply (minorRadius / majorRadius);
  gp_Vec V = gp_Vec (pos.XDirection());
  V.Add (V1);
  return  gp_Ax1(pos.Location(), gp_Dir(V));
}

 gp_Ax1 gp_Hypr::Asymptote2 () const
{
  Standard_ConstructionError_Raise_if (majorRadius <= gp::Resolution(), "");
  gp_Vec V1 = gp_Vec (pos.YDirection());
  V1.Multiply (-minorRadius / majorRadius);
  gp_Vec V = gp_Vec (pos.XDirection());
  V.Add (V1);
  return  gp_Ax1( pos.Location(), gp_Dir(V));
}

 const gp_Ax1& gp_Hypr::Axis () const
{ return pos.Axis(); }

 gp_Hypr gp_Hypr::ConjugateBranch1 () const
{
  return gp_Hypr (gp_Ax2(pos.Location(), pos.Direction(), pos.YDirection()),
		  minorRadius, 
		  majorRadius);
}

 gp_Hypr gp_Hypr::ConjugateBranch2 () const
{
  gp_Dir D = pos.YDirection();
  D.Reverse ();
  return gp_Hypr (gp_Ax2(pos.Location(), pos.Direction(), D),
		  minorRadius, 
		  majorRadius);
}

 gp_Ax1 gp_Hypr::Directrix1 () const
{
  double E = Eccentricity();
  gp_XYZ Orig = pos.XDirection().XYZ();
  Orig.Multiply (majorRadius/E);
  Orig.Add (pos.Location().XYZ());
  return gp_Ax1 (gp_Pnt(Orig), pos.YDirection());
}

 gp_Ax1 gp_Hypr::Directrix2 () const
{
  double E = Eccentricity();
  gp_XYZ Orig = pos.XDirection().XYZ();
  Orig.Multiply (-majorRadius/E);
  Orig.Add (pos.Location().XYZ());
  return gp_Ax1 (gp_Pnt(Orig), pos.YDirection());
}

 double gp_Hypr::Eccentricity () const
{
  Standard_DomainError_Raise_if (majorRadius <= gp::Resolution(), "");
  return sqrt(majorRadius * majorRadius +
	      minorRadius * minorRadius) / majorRadius;
}

 double gp_Hypr::Focal () const
{
  return 2.0 * sqrt(majorRadius * majorRadius +
		    minorRadius * minorRadius);
}

 gp_Pnt gp_Hypr::Focus1 () const
{
  double C = sqrt(majorRadius * majorRadius +
			 minorRadius * minorRadius);
  const gp_Pnt& PP = pos.Location  ();
  const gp_Dir& DD = pos.XDirection();
  return gp_Pnt (PP.X() + C * DD.X(),
		 PP.Y() + C * DD.Y(),
		 PP.Z() + C * DD.Z());
}

 gp_Pnt gp_Hypr::Focus2 () const
{
  double C = sqrt(majorRadius * majorRadius +
			 minorRadius * minorRadius);
  const gp_Pnt& PP = pos.Location  ();
  const gp_Dir& DD = pos.XDirection();
  return gp_Pnt (PP.X() - C * DD.X(),
		 PP.Y() - C * DD.Y(),
		 PP.Z() - C * DD.Z());
}

 const gp_Pnt& gp_Hypr::Location () const
{ return pos.Location(); }

   double gp_Hypr::MajorRadius() const
{ return majorRadius; }

   double gp_Hypr::MinorRadius() const
{ return minorRadius; }

 gp_Hypr gp_Hypr::OtherBranch () const
{
  gp_Dir D = pos.XDirection ();
  D.Reverse ();
  return gp_Hypr (gp_Ax2(pos.Location(), pos.Direction(), D),
		  majorRadius, minorRadius);
}

 double gp_Hypr::Parameter() const
{
  Standard_DomainError_Raise_if (majorRadius <= gp::Resolution(), "");
  return (minorRadius * minorRadius) / majorRadius;
}

   const gp_Ax2& gp_Hypr::Position() const
{ return pos; }

 gp_Ax1 gp_Hypr::XAxis () const
{return gp_Ax1 (pos.Location(), pos.XDirection());}

 gp_Ax1 gp_Hypr::YAxis () const
{return gp_Ax1 (pos.Location(), pos.YDirection());}

 void gp_Hypr::Rotate (const gp_Ax1& A1,
			     const double Ang)
{ pos.Rotate(A1, Ang); }

 gp_Hypr gp_Hypr::Rotated (const gp_Ax1& A1,
				 const double Ang) const
{
  gp_Hypr H = *this;
  H.pos.Rotate(A1, Ang);
  return H; 
}

 void gp_Hypr::Scale (const gp_Pnt& P,
			    const double S)
{
  majorRadius *= S;
  if (majorRadius < 0) majorRadius = - majorRadius;
  minorRadius *= S;
  if (minorRadius < 0) minorRadius = - minorRadius;
  pos.Scale(P, S);
}

 gp_Hypr gp_Hypr::Scaled (const gp_Pnt& P,
				const double S) const
{
  gp_Hypr H = *this;
  H.majorRadius *= S;
  if (H.majorRadius < 0) H.majorRadius = - H.majorRadius;
  H.minorRadius *= S;
  if (H.minorRadius < 0) H.minorRadius = - H.minorRadius;
  H.pos.Scale(P, S);
  return H; 
}

 void gp_Hypr::Transform (const gp_Trsf& T)
{ 
  majorRadius *= T.ScaleFactor();
  if (majorRadius < 0) majorRadius = - majorRadius;
  minorRadius *= T.ScaleFactor();
  if (minorRadius < 0) minorRadius = - minorRadius;
  pos.Transform(T);
}

 gp_Hypr gp_Hypr::Transformed (const gp_Trsf& T) const
{
  gp_Hypr H = *this;
  H.majorRadius *= T.ScaleFactor();
  if (H.majorRadius < 0) H.majorRadius = - H.majorRadius;
  H.minorRadius *= T.ScaleFactor();
  if (H.minorRadius < 0) H.minorRadius = - H.minorRadius;
  H.pos.Transform(T);
  return H; 
}

 void gp_Hypr::Translate (const gp_Vec& V)
{ pos.Translate(V); }

 gp_Hypr gp_Hypr::Translated (const gp_Vec& V) const
{
  gp_Hypr H = *this;
  H.pos.Translate(V);
  return H; 
}

 void gp_Hypr::Translate (const gp_Pnt& P1,
				const gp_Pnt& P2)
{pos.Translate(P1,P2);}

 gp_Hypr gp_Hypr::Translated (const gp_Pnt& P1,
				    const gp_Pnt& P2) const
{
  gp_Hypr H = *this;
  H.pos.Translate(P1, P2);
  return H; 
}